home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / pyshared / whisperBack / mail.py < prev    next >
Encoding:
Python Source  |  2012-12-13  |  5.6 KB  |  179 lines

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. ########################################################################
  5. # WhisperBack - Send feedback in an encrypted mail
  6. # Copyright (C) 2009-2012 Tails developers <amnesia.org>
  7. #
  8. # This file is part of WhisperBack
  9. #
  10. # WhisperBack is  free software; you can redistribute  it and/or modify
  11. # it under the  terms of the GNU General Public  License as published by
  12. # the Free Software Foundation; either  version 3 of the License, or (at
  13. # your option) any later version.
  14. # This program  is distributed in the  hope that it will  be useful, but
  15. # WITHOUT   ANY  WARRANTY;   without  even   the  implied   warranty  of
  16. # MERCHANTABILITY  or FITNESS  FOR A  PARTICULAR PURPOSE.   See  the GNU
  17. # General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21. ########################################################################
  22.  
  23. """WhisperBack mailing library
  24.  
  25. """
  26.  
  27. import smtplib
  28. import socket
  29. from email.mime.text import MIMEText
  30. import gnutls.errors
  31. import time
  32.  
  33. def create_message (from_address, to_address, subject, message):
  34.     """Create a plaintext mail
  35.  
  36.     This is from an example from doc.python.org
  37.  
  38.     @param from_address The sender's address
  39.     @param to_address The recipient address
  40.     @param subject The topic
  41.     @param message The content of the text message
  42.  
  43.     @return the message to send
  44.     """
  45.  
  46.     msg = MIMEText(message)
  47.     msg['Subject'] = subject
  48.     msg['From'] = from_address
  49.     msg['To'] = to_address
  50.  
  51.     return msg.as_string()
  52.  
  53. #pylint: disable=R0913
  54. def send_message_tls (from_address, to_address, message, host="localhost",
  55.                     port=25, tls_cafile=None):
  56.     """Sends a mail
  57.  
  58.     This is from an example from doc.python.org
  59.  
  60.     @param from_address The sender's address
  61.     @param to_address The recipient address
  62.     @param message The content of the mail
  63.     @param host The host of the smtp server to connect to
  64.     @param port The port of the smtp server to connect to
  65.     @param tls_ca Certificate authority file passed to the socket moduleΓÇÖs ssl() function.
  66.     """
  67.     # Send the message via our own SMTP server, but don't include the
  68.     # envelope header.
  69.     # We set a long timeout because Tor is slow
  70.     smtp = smtplib.SMTP(timeout=120)
  71.     smtp.connect(host, port)
  72.     (resp, reply) = smtp.starttls(cafile = tls_cafile)
  73.     # Default python let you continue in cleartext if starttls
  74.     # fails, while you expect to have an encrypted connexion
  75.     if resp != 220:
  76.         raise TLSError("%s answered %i, %s when trying to start TLS"
  77.                        % (host, resp, reply))
  78.     else:
  79.         smtp.sendmail(from_address, [to_address], message)
  80.         smtp.quit()
  81.  
  82. class TLSError(Exception):
  83.     """Exception raised if problem happens in STARTTLS step"""
  84.     pass
  85.  
  86. # This is a monkey patch to make the starttls function of libsmtp use
  87. # starttls, as the buildin doesn't really check certificates and doesn't
  88. # have a timeout parameter
  89. #pylint: disable=W0613
  90. def starttls(self, keyfile = None, certfile = None, cafile=None):
  91.     """Puts the connection to the SMTP server into TLS mode.
  92.  
  93.     If the server supports TLS, this will encrypt the rest of the SMTP
  94.     session.
  95.  
  96.     """
  97.     (resp, reply) = self.docmd("STARTTLS")
  98.     if resp == 220:
  99.  
  100.         from gnutls.crypto import X509Certificate
  101.         from gnutls.connection import ClientSession, X509Credentials
  102.         # Don't worry, this is a monkey patch
  103.         #pylint: disable=W0621
  104.         import struct
  105.  
  106.         tv = struct.pack('ii', int(6), int(0))
  107.         self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, tv)
  108.  
  109.         if cafile:
  110.             ca = X509Certificate(open(cafile).read())
  111.         # XXX: use CRL
  112.         #crl = X509CRL(open(certs_path + '/crl.pem').read())
  113.         #cred = X509Credentials(trusted=[ca], crl_list=[crl])
  114.         cred = X509Credentials(trusted=[ca])
  115.         session = ClientSession(self.sock, cred)
  116.  
  117.         while True:
  118.             try:
  119.                 session.handshake()
  120.                 session.verify_peer()
  121.                 break
  122.             except gnutls.errors.OperationWouldBlock:
  123.                 time.sleep(0.1)
  124.  
  125.         def tls_quit():
  126.             """Terminate the SMTP session."""
  127.             self.docmd("quit")
  128.             while True:
  129.                 try:
  130.                     self.sock.bye()
  131.                     break
  132.                 except gnutls.errors.OperationWouldBlock:
  133.                     time.sleep(0.1)
  134.             self.close()
  135.  
  136.         self.quit = tls_quit
  137.  
  138.         self.sock = session
  139.         self.file = SSLFakeFile(session)
  140.  
  141.         # RFC 3207:
  142.         # The client MUST discard any knowledge obtained from
  143.         # the server, such as the list of SMTP service extensions,
  144.         # which was not obtained from the TLS negotiation itself.
  145.         self.helo_resp = None
  146.         self.ehlo_resp = None
  147.         self.esmtp_features = {}
  148.         self.does_esmtp = 0
  149.     return (resp, reply)
  150.  
  151. class SSLFakeFile:
  152.     """A fake file like object that really wraps a SSLObject.
  153.  
  154.     It only supports what is needed in smtplib.
  155.     """
  156.     def __init__(self, sslobj):
  157.         self.sslobj = sslobj
  158.  
  159.     #pylint: disable=C0111
  160.     def readline(self):
  161.         string = ""
  162.         char = None
  163.         while char != "\n":
  164.             while True:
  165.                 try:          
  166.                     char = self.sslobj.recv(1)
  167.                     string += char
  168.                     break
  169.                 except gnutls.errors.OperationWouldBlock:
  170.                     time.sleep(0.1)
  171.         return string
  172.  
  173.     #pylint: disable=C0111
  174.     def close(self):
  175.         pass
  176.  
  177. smtplib.SMTP.starttls = starttls
  178.